package club.gggd.qqrobot.listener;

import club.gggd.qqrobot.enums.GachaTypeEnum;
import club.gggd.qqrobot.enums.PrayEnum;
import club.gggd.qqrobot.pojo.gacha.GachaApiResult;
import club.gggd.qqrobot.pojo.gacha.GachaPage;
import club.gggd.qqrobot.pojo.gacha.GachaRecord;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import love.forte.simboot.annotation.Filter;
import love.forte.simboot.annotation.FilterValue;
import love.forte.simboot.annotation.Listener;
import love.forte.simboot.filter.MatchType;
import love.forte.simbot.event.GroupMessageEvent;
import org.springframework.stereotype.Component;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description 原神祈愿分析
 * @Author srx
 * @date 2022/9/6 17:07
 */
@Component
@Slf4j
public class GachaListener {

    private String trueBaseUrl = "https://hk4e-api.mihoyo.com/event/gacha_info/api/getGachaLog?";

    @Listener
    @Filter(value = "#抽卡分析{{url}}", matchType = MatchType.REGEX_MATCHES)
    public void listen(GroupMessageEvent event, @FilterValue("url") String url) {
        event.getGroup().sendBlocking("分析中，请等待");
        String data = getRecord(url);
        event.getGroup().sendBlocking(data);

    }

    /**
     * 获取记录
     * @param url
     * @return
     */
    private String getRecord(String url){
        // 定义常驻、角色、武器池记录
        List<GachaRecord> changzhu = new ArrayList<>();
        List<GachaRecord> juese = new ArrayList<>();
        List<GachaRecord> wuqi = new ArrayList<>();

        // 定义池子 200：常驻  301：角色  302：武器
        int[] gachaTypes = new int[]{200, 301, 302};

        // 获取真实请求地址
        String base = getRequestUrl(url);

        // 获取记录
        for (int i = 0; i < gachaTypes.length; i++) {
            // 拼接地址
            StringBuffer middle = new StringBuffer(base);
            middle.append("gacha_type=" + gachaTypes[i] + "&");
            middle.append("page=1&");
            middle.append("size=20&");
            String baseUrl = middle.toString();
            String end_id = "0";

            while (true){
                StringBuilder end = new StringBuilder(baseUrl);
                end.append("end_id=" + end_id);

                log.info("查询卡池：{}, end_id={}", gachaTypes[i], end_id);
                // 获取抽卡记录
                List<GachaRecord> gachaRecords = parseJson(end.toString());

                // 如果查询到的数据为空表示查完了
                if(gachaRecords.isEmpty()){
                    log.info("卡池{}查询完毕", gachaTypes[i]);
                    break;
                }

                // 整理卡池数据
                if(gachaTypes[i] == PrayEnum.PERMANENT.getType()){
                    changzhu.addAll(gachaRecords);
                }else if(gachaTypes[i] == PrayEnum.ROLE.getType()){
                    juese.addAll(gachaRecords);
                }else {
                    wuqi.addAll(gachaRecords);
                }

                // 得到最后一个元素的end_id
                end_id = gachaRecords.get(gachaRecords.size() - 1).getId();
                try {
                    // 每个查询需要间隔一段时间
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        // 全部查询完毕，执行分析
        String result = analysis(changzhu, juese, wuqi);
        return result;
    }

    /**
     * 获取真实请求地址
     * @param url
     * @return
     */
    private String getRequestUrl(String url){
        StringBuilder sb = new StringBuilder();
        sb.append(trueBaseUrl);
        sb.append(url.split("\\?")[1].split("#")[0]).append("&");
        return sb.toString();
    }

    /**
     * 获取抽卡记录
     * @param url
     * @return
     */
    private List<GachaRecord> parseJson(String url){
        String json = HttpUtil.get(url);
        GachaApiResult result = JSON.parseObject(json, GachaApiResult.class);
        if(result.getRetcode() == -101){
            // todo 这里需要优化，可使用全局异常处理
            throw new RuntimeException("URL已过期");
        }
        GachaPage page = result.getData();
        List<GachaRecord> records = page.getList();
        return records;
    }

    /**
     * 分析
     * @param changzhu
     * @param juese
     * @param wuqi
     * @return
     */
    private String analysis(List<GachaRecord> changzhu, List<GachaRecord> juese, List<GachaRecord> wuqi){
        StringBuffer sb = new StringBuffer();

        // 常驻池分析
        int changzhuNotFiveStartNum = getNotFiveStartNum(changzhu);
        sb.append(PrayEnum.PERMANENT.getName() + "共" + changzhu.size() + "抽，已累计" + changzhuNotFiveStartNum + "抽未出金");
        sb.append("\n");

        String changzhuFiveStartRecord = getFiveStartRecord(changzhu);
        sb.append("五星历史记录：" + changzhuFiveStartRecord).append("\n");

        List<String> changzhuStartRecord = getStartRecord(changzhu);
        changzhuStartRecord.forEach(cz -> sb.append(cz).append("\n"));
        sb.append("\n");


        //角色池分析
        int jueseNotFiveStartNum = getNotFiveStartNum(juese);
        sb.append(PrayEnum.ROLE.getName() + "共" + juese.size() + "抽，已累计" + jueseNotFiveStartNum + "抽未出金");
        sb.append("\n");

        String jueseFiveStartRecord = getFiveStartRecord(juese);
        sb.append("五星历史记录：" + jueseFiveStartRecord).append("\n");

        List<String> jueseStartRecord = getStartRecord(juese);
        jueseStartRecord.forEach(j -> sb.append(j).append("\n"));
        sb.append("\n");


        //武器池分析
        int wuqiNotFiveStartNum = getNotFiveStartNum(wuqi);
        sb.append(PrayEnum.ARMS.getName() + "共" + wuqi.size() + "抽，已累计" + wuqiNotFiveStartNum + "抽未出金");
        sb.append("\n");

        String wuqiFiveStartRecord = getFiveStartRecord(wuqi);
        sb.append("五星历史记录：" + wuqiFiveStartRecord).append("\n");

        List<String> wuqiStartRecord = getStartRecord(wuqi);
        wuqiStartRecord.forEach(w -> sb.append(w).append("\n"));

        return sb.toString();
    }

    /**
     * 获取累计未出五星次数
     * @param list
     * @return
     */
    private int getNotFiveStartNum(List<GachaRecord> list){
        int num;
        List<GachaRecord> fiveStartList = list.stream()
                .filter(x -> x.getRank_type() == GachaTypeEnum.FIVE.getCode())
                .collect(Collectors.toList());

        if(fiveStartList != null && !fiveStartList.isEmpty()){
            num = list.indexOf(fiveStartList.get(0));
        }else{
            num = list.size();
        }

        return num;
    }

    /**
     * 获取五星历史记录
     * @param list
     * @return
     */
    private String getFiveStartRecord(List<GachaRecord> list){
        StringBuffer sb = new StringBuffer();

        Collections.reverse(list);
        List<GachaRecord> fiveStartList = list.stream()
                .filter(x -> x.getRank_type() == GachaTypeEnum.FIVE.getCode())
                .collect(Collectors.toList());

        if(fiveStartList != null && !fiveStartList.isEmpty()){
            int times = 0;
            for (GachaRecord record : fiveStartList) {
                sb.append(record.getName()).append("[").append(list.indexOf(record) - times).append("] ");
                times = list.indexOf(record);
            }
        }else {
            sb.append("暂无记录");
        }

        return sb.toString();
    }

    /**
     * 获取各星级出货次数与五星平均出货次数
     * @param list
     * @return
     */
    public static List<String> getStartRecord(List<GachaRecord> list){
        List<String> data = new ArrayList<>();

        if(list.size() > 0){
            long fiveCount;
            long fourCount;
            long threeCount;

            fiveCount = list.stream().filter(l -> l.getRank_type() == GachaTypeEnum.FIVE.getCode()).count();
            fourCount = list.stream().filter(l -> l.getRank_type() == GachaTypeEnum.FOUR.getCode()).count();
            threeCount = list.stream().filter(l -> l.getRank_type() == GachaTypeEnum.THREE.getCode()).count();

            DecimalFormat df = new DecimalFormat("0.00");
            data.add(new StringBuffer()
                    .append(GachaTypeEnum.FIVE.getName()).append("：").append(fiveCount).append(" [")
                    .append(df.format((float) fiveCount / list.size() * 100)).append("%]").toString());

            data.add(new StringBuffer()
                    .append(GachaTypeEnum.FOUR.getName()).append("：").append(fourCount).append(" [")
                    .append(df.format((float) fourCount / list.size() * 100)).append("%]").toString());

            data.add(new StringBuffer()
                    .append(GachaTypeEnum.THREE.getName()).append("：").append(threeCount).append(" [")
                    .append(df.format((float) threeCount / list.size() * 100)).append("%]").toString());

            data.add(new StringBuffer().append("五星平均出货次数为：").append(df.format((float) list.size() / fiveCount)).toString());
        }

        return data;
    }
}
